package com.gitee.wsl.compose.chart.sample.polar

import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.unit.dp
import com.gitee.wsl.common.ui.draw.style.LineStyle
import com.gitee.wsl.compose.chart.Chart
import com.gitee.wsl.compose.chart.ChartLayout
import com.gitee.wsl.compose.chart.ExperimentalKoalaPlotApi
import com.gitee.wsl.compose.chart.KoalaPlotTheme.axisThemeStyle
import com.gitee.wsl.compose.chart.SelectChangedListener
import com.gitee.wsl.compose.chart.SelectCheck
import com.gitee.wsl.compose.chart.generateHueColorPalette
import com.gitee.wsl.compose.chart.legend.Flow
import com.gitee.wsl.compose.chart.legend.Legend
import com.gitee.wsl.compose.chart.legend.LegendLocation
import com.gitee.wsl.compose.chart.polar.PolarGraph
import com.gitee.wsl.compose.chart.polar.PolarPlotSeries
import com.gitee.wsl.compose.chart.polar.axis.rememberCategoryAngularAxisModel
import com.gitee.wsl.compose.chart.polar.axis.rememberFloatRadialAxisModel
import com.gitee.wsl.compose.chart.polar.model.PolarPoint
import com.gitee.wsl.compose.chart.polar.style.PolarGraphDefaults
import com.gitee.wsl.compose.chart.sample.ChartTitle
import com.gitee.wsl.compose.chart.sample.HoverSurface
import com.gitee.wsl.compose.chart.sample.PopulationData
import com.gitee.wsl.compose.chart.sample.SampleView
import com.gitee.wsl.compose.chart.sample.ThumbnailTheme
import com.gitee.wsl.compose.chart.sample.padding
import com.gitee.wsl.compose.chart.sample.paddingMod
import com.gitee.wsl.compose.ui.widget.Symbol
import com.gitee.wsl.ext.number.toString


val radialLinePlotSample = object : SampleView {
    override val name: String = "Radial Line Plot"

    override val thumbnail = @Composable {
        ThumbnailTheme {
            RadialLinePlotSample(true, name)
        }
    }

    override val content: @Composable () -> Unit = @Composable {
        RadialLinePlotSample(false, "Population (Millions)")
    }
}

@OptIn(ExperimentalKoalaPlotApi::class)
@Composable
@Suppress("MagicNumber")
private fun RadialLinePlotSample(thumbnail: Boolean, title: String) {
    ChartLayout(
        modifier = paddingMod,
        title = { ChartTitle(title) },
        legend = {selected,listener-> LegendView(thumbnail,selected,listener) },
        legendLocation = LegendLocation.BOTTOM
    ) {
        val ram = rememberFloatRadialAxisModel(listOf(0f, 0.5f, 1f, 1.5f, 2f, 2.5f, 3f)) // population in millions
        val aam = rememberCategoryAngularAxisModel(PopulationData.years)

        val angularAxisGridLineStyle = if (thumbnail) {
            LineStyle(SolidColor(Color.LightGray), strokeWidth = 1.dp)
        } else {
            axisThemeStyle.majorGridlineStyle
        }

        Chart.PolarGraph(
            ram,
            aam,
            radialAxisLabels = { if (!thumbnail) Text(it.toString(1)) },
            { if (!thumbnail) Text(it.toString()) },
            polarGraphStyle = PolarGraphDefaults.Default()
                .copy(
                    angularAxisGridLineStyle = angularAxisGridLineStyle,
                    radialAxisGridLineStyle = angularAxisGridLineStyle
                )
        ) {
            PopulationData.data.forEach { (category, data) ->
                PolarPlotSeries(
                    object : AbstractList<PolarPoint<Float, Int>>() {
                        override val size: Int
                            get() = PopulationData.years.size

                        override fun get(index: Int): PolarPoint<Float, Int> {
                            return PolarPoint(data[index] / 1E6f, PopulationData.years[index])
                        }
                    },
                    lineStyle = LineStyle(SolidColor(colorMap[category]!!), strokeWidth = 1.dp),
                    symbols = {
                        Symbol(
                            shape = CircleShape,
                            fillBrush = SolidColor(colorMap[category]!!),
                            modifier = Modifier.then(
                                if (!thumbnail) {
                                    Modifier.hoverableElement {
                                        HoverSurface {
                                            Text(
                                                "${(it.r * 1E6).toInt()}",
                                                style = MaterialTheme.typography.bodySmall
                                            )
                                        }
                                    }
                                } else {
                                    Modifier
                                }
                            )
                        )
                    }
                )
            }
        }
    }
}

private val colorMap = buildMap {
    val colors = generateHueColorPalette(PopulationData.data.size)
    var i = 0
    PopulationData.data.forEach {
        put(it.key, colors[i++])
    }
}


@Composable
private fun LegendView(thumbnail: Boolean = false,selectCheck: SelectCheck,selectChangedListener: SelectChangedListener?) {
    val cities = PopulationData.data.keys.sorted()

    if (!thumbnail) {
        Surface(shadowElevation = 2.dp) {
            Legend.Flow(
                itemCount = cities.size,
                symbol = { i ,selected->
                    Symbol(
                        shape = CircleShape,
                        modifier = Modifier.size(padding),
                        fillBrush = SolidColor(colorMap[cities[i]] ?: Color.Black)
                    )
                },
                label = { i,selected,listener ->
                    Text(cities[i].display)
                },
                modifier = paddingMod,
                selectCheck = selectCheck,
                selectChangedListener = selectChangedListener
            )
        }
    }
}
